import abc
from typing import List, TypeVar, Generic, Union, Any

from pywebio.io_ctrl import Output
from pywebio.output import OutputPosition

from emi.bar.data import BarData
from emi.bar.db import BarSource
from emi.model import PageResult,default_page_result
from emi.model.loader import DataLoader, SortItem
from emi.util import AsyUtil, NumUtils
from emiui.pywebio.widget import DataLoaderView
from emiui import UISession
import pywebio
import pywebio_battery
from pywebio import pin, output


class BarSourceView(DataLoaderView[str,BarData]):

    """
    与DataListView不同，这里是包含排序功能的。
    """
    def __init__(self,
                 name: str,
                 source:BarSource,
                 ui_session: UISession = None,
                 sort_items: List[SortItem[BarData]] = None,  ## 排序方式
                 page_size = 50
                 ):
        self._bar_source = source
        self._day_list = self._bar_source.get_day_list()
        if len(self._day_list) > 0:
            self._newest_day = self._day_list[-1]
        else:
            self._newest_day = None
        loader = self.create_loader(source)
        super().__init__(name,loader,sort_items=sort_items,ui_session=ui_session,page_size=page_size)

    def getBarSource(self):
        return self._bar_source

    def create_loader(self,source:BarSource)->DataLoader[Any,BarData]:
        symbol_list = source.get_symbol_list()
        return DataLoader.make(symbol_list)

    def get_item_view(self,offset:int,is_head:bool,data:BarData):
        if is_head:
            ## 表头
            return ["序号", "code", "更新时间", "pnl","close"]
        else:
            return [
                str(offset),
                data.symbol,
                "-" if data.is_null() else f"{data.datetime.date()}",
                "-" if data.is_null() else put_pnl(data),
                "-" if data.is_null() else put_close(data),
            ]


    def load_item_data(self,items:List[str])->List[BarData]:
        data_list = []
        for symbol in items:
            bar = None
            if self._newest_day:
                bars = self._bar_source.get_bars_recently(symbol=symbol,
                                                          count=1,
                                                          time=self._newest_day,
                                                          is_before=True)
                if bars:
                    bar = bars[-1]
            if bar is None:
                data_list.append(BarData.null(symbol))
            else:
                data_list.append(bar)

        return data_list



def put_pnl(data:Union[float,BarData]):
    if isinstance(data,BarData):
        pnl = data.pnl
    else:
        pnl = data
    if pnl is None:
        return  output.put_text("-").style('color: grey')
    if NumUtils.is_equal(pnl,0):
        return  output.put_text("0.0%").style('color: grey')
    else:
        if pnl > 0:
            return output.put_text(f"+{pnl:.1f}%").style('color: red')
        else:
            return output.put_text(f"{pnl:.1f}%").style('color: green')

def put_close(data:Union[float,BarData],adjust_price = True):

    if data is None:
        return output.put_text("-").style('color: grey')
    if isinstance(data,BarData):
        price = data.close
        return put_price(price/data.price_adjust if adjust_price else price,pnl=data.pnl)
    return put_price(data,pnl=None)

def put_price(price: float,pnl =None):
    """

    :param price:
    :param pnl: 根据pnl值选择颜色样式
    :return:
    """
    if price is None:
        return output.put_text("-").style('color: grey')

    style = 'color: grey'
    if pnl is not None:
        if pnl > 0.001:
                style = 'color: red'
        elif pnl < -0.01:
                style = 'color: green'
    return output.put_text(f"{price:.2f}").style(style)